#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qmessagebox.h"

#include "connectpage.h"
#include "tagread.h"

//第三方库
#include "GReader.h"
#include "message.h"
#include "delegate.h"

#include "QDebug"
#include <QString>
#include "string"
#include <QTimer>

extern ConnectPage *myPage ;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //一般构造函数用来初始化页面，数据等
    DevContPage = new ConnectPage();
    ReadPage = new TAGRead();
    chargetimer = new QTimer(this);
    state = IDLE;
    //捕捉菜单栏点击连接设备的事件
    connect(ui->TCP_Connect , &QAction::triggered , this ,[=]()
    {
        qDebug("打开TCP客户端\r\n");
        DevContPage->show();
        /* 在TCP页面需要输入IP信息，创建TCP连接，在不同的页面都可以通过创建的连接进行通信，因此句柄不能消失 */
    });

    connect(ui->myreadTag , &QAction::triggered , this ,[=]()
    {
        qDebug("打开读标签页面\r\n");
        ReadPage->show();
    });
    //捕捉菜单栏点击读EPC的事件
    connect(ui->ReadEPC , &QAction::triggered , this ,[=](){});

    //接收连接页面发来的信号，该页面中的回调函数会将收到的数据发送过来
    //connect(DevContPage , SIGNAL(ReadTagRetuenData) ,this , SLOT(test(LogBaseEpcInfo *str)));
    connection = connect(ConnectPage::myPage , &ConnectPage::ReadTagRetuenData , [this](LogBaseEpcInfo str){
        this->receiveDataRefresh(str);
    });

    connect(chargetimer, SIGNAL(timeout()), this, SLOT(handleTimeout()));

}

MainWindow::~MainWindow()
{
    delete ui;
}

/* 点击TCP客户端时，弹出连接页面 */
void TCPConnectDevice()
{
    qDebug("打开TCP客户端\r\n");
}


//读取EPC标签信息
void MainWindow::on_ReadEPC_triggered()
{
    //连接成功的情况下
    //组织数据包
    //使用TCP发送信息
    //std::cout << "connect state" << DevContPage->gclient->isOpened ;//程序运行这句话时会卡死
    if(!DevContPage->gclient)
    {
        QMessageBox::about(this,"","设备未连接");
        return ;
    }
    qDebug("DevContPage有效对象\r\n");
    if(!DevContPage->gclient->isOpened )
    {
        QMessageBox::about(this,"","设备未连接");
        return ;
    }

    //组织发送的信息
    MsgBaseInventoryEpc msg1;
    memset(&msg1, 0, sizeof(msg1));
    msg1.AntennaEnable = AntennaNo_1;
    msg1.InventoryMode = 0;
    msg1.ReadTid.Mode = 0;
    msg1.ReadTid.Len = 6;

    /* 发送读EPC指令 */
    SendSynMsg(DevContPage->gclient, EMESS_BaseInventoryEpc, &msg1);//只是发送停止指令
}

void MainWindow::on_ReadWord_clicked()
{
    QString selectInput = ui->WordSelect->currentText();

    //qDebug()<<"读Word" << selectInput.toUtf8();
    state = readUserdata;
    int addr = 0;
    int len = 1;

    if(selectInput == "IO Control Word"){
        addr = 0xF0;
    }
    else if(selectInput == "temperature"){
        addr = 0x00;
    }
    else if(selectInput == "humidity"){
        addr = 0x01;
    }
    ReadTag(addr,len , SINGEL);
}

void MainWindow::on_WriteWord_clicked()
{
    QString selectInput = ui->WordSelect->currentText();//下拉框选项
    qDebug()<<"写Word" << selectInput.toUtf8();

    QString data =  ui->WriteData->text();//获取写输入框文本
    char * WriteData = data.toLatin1().data();//要写的内容

    //组织要发送的信息
    int writeAddr = 0;
    if(selectInput == "IO Control Word"){
        writeAddr = 0xF0;              //写入数据的起始地址
    }
    else if(selectInput == "temperature"){
        writeAddr = 0x00;
    }
    else if(selectInput == "humidity"){
        writeAddr= 0x01;
    }

    WriteTag(writeAddr,WriteData);

}


//页面数据刷新
 void MainWindow::receiveDataRefresh(LogBaseEpcInfo msg)
 {
    qDebug("主页面接收数据");
    QString strEpc((char*) msg.Epc);
    QString strUser((char*) msg.Userdata);
    qDebug() << "Userdata:" << strUser;
    qDebug() << "state:" << state;
    //不同状态下刷新的组件不同
    switch (state) {
    case IDLE:
        break;

    case readUserdata:
        ui->ReadEPCText->setText(strEpc);
        ui->ReadDataText->setText(strUser);
        break;

    case chargeing:

        break;

    case readTempHumi:
        /*处理1D003C00*/
        bool ret ;
        int intTemp = strUser.toInt(&ret, 16);
        qDebug() << "intTemp" <<intTemp;
        if(ret){
            /* 转换成功 */
            QString temp = QString::number(intTemp>>24);
            QString humi = QString::number((intTemp&0xff00)>>8);
            temp.append("C");
            humi.append("%");
            qDebug() << "temp" <<temp ;
            qDebug() << "humi" <<humi ;

            ui->ReadTemp->setText(temp);
            ui->ReadHumi->setText(humi);
        }
        else{
            /* 转换失败 */
            qDebug() << "转换失败" ;
        }
        break;
    }
 }

void MainWindow::on_ReadTempHumi_clicked()
{
    //先判断阅读器有没有连接
    int ret = DevContPage->GetConnectState();
    if(ret==Disconnected)
    {
        QMessageBox::about(this,"连接状态","连接已断开，请重新连接阅读器");
        return;
    }
    //获取设定的充电时间
    QString time = ui->chargeTime->text();
    qDebug() << "输入时间" << time.toInt();
    chargeTimeS = time.toInt();

    PowerCharge(chargeTimeS);

}

void MainWindow::PowerCharge(int ChargeTime)
{
    //充电需要一个定时器
    //写IO 为0000
    state = chargeing;           //当前状态为充电状态
    WriteTag(0xF0,"0000");       //防止在充电过程中总是唤醒MCU增加功耗
    disconnect(connection);      //防止总是刷新主页数据
    ReadTag(0xF0,1 , CONTINUOUS);//连续读一个随机内容，目的是持续向外辐射能量 */

    chargetimer->start(1000);//单位是ms,一秒回调一次
    processStep = 100/chargeTimeS;
}


/* 定时器超时回调 */
void MainWindow::handleTimeout(void)
{
    qDebug() << "定时时间到了" ;
    /* 刷新进度条 */
    static int value = 0;
    value += processStep;
    ui->chargeProgress->setValue(value);

    if(chargetimer->isActive() && (--chargeTimeS) == 0)
    {
        chargetimer->stop();
        ui->chargeProgress->setValue(100);
        value = 0;
        qDebug() << "handleTimeout" ;
        ReadTempHumi();//读一次温湿度
    }
}

void MainWindow::on_StopButton_clicked()
{
    //停止充电(停止发送信息)
    //进度条停止
    ui->chargeProgress->setValue(0);
    this->MsgStop();
}

//停止读取
void MainWindow::MsgStop()
{
    //发送停止信息
    MsgBaseStop stop;
    memset(&stop, 0, sizeof(stop));//把停止地址里的内容清零
    SendSynMsg(DevContPage->gclient, EMESS_BaseStop, &stop);//只是发送停止指令
}

void MainWindow::WriteTag(int addr,char *HexStrNum)
{
    /* 设置IO control Word为A600*/
    MsgBaseWriteEpc writeMsg;
    memset(&writeMsg, 0, sizeof(writeMsg));
    writeMsg.AntennaEnable = AntennaNo_1;   //天线端口
    writeMsg.Area = 3;                      //往用户数据区写数据
    writeMsg.Start = addr;
    memcpy(writeMsg.StrHexWriteData , HexStrNum , strlen(HexStrNum));//要写的内容需要是十六进制字符
    SendSynMsg(DevContPage->gclient, EMESS_BaseWriteEpc, &writeMsg);

}
void MainWindow::ReadTag(int addr,int len , ReadMode mode)
{
    MsgStop();
    MsgBaseInventoryEpc msg1;
    memset(&msg1, 0, sizeof(msg1));
    msg1.AntennaEnable = AntennaNo_1;
    msg1.InventoryMode = mode;//读一次
    msg1.ReadUserdata.Start = addr;
    msg1.ReadUserdata.Len = len;
    SendSynMsg(DevContPage->gclient, EMESS_BaseInventoryEpc, &msg1);
}

/* 读温湿度 */
void MainWindow::ReadTempHumi(void)
{
    /* 先写IOCtrlWord为0，目的是让AUX不输出，持续向外辐射能量，给射频能量采集， */
    /* 过一段时间再写IOCtrlWord为A600，目的是使能SPI，并打开AUX，此时向外辐射能量，AUX就能唤醒MCU*/
    state = readTempHumi;
    connection = connect(ConnectPage::myPage , &ConnectPage::ReadTagRetuenData , [this](LogBaseEpcInfo str){
        this->receiveDataRefresh(str);
    });

    MsgStop();
    WriteTag(0xF0,"A600");
    MsgStop();
    ReadTag(0x00, 2 , SINGEL);
}
